home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libgutil / bitmap.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  11KB  |  621 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    bitmap -
  19.  *        Support for the allocation, manipulation, and display 
  20.  *    of bitmaps.
  21.  *
  22.  *                Paul Haeberli - 1985
  23.  *
  24.  *
  25.  *    exports
  26.  *
  27.     Bitmap *bmnew(xsize,ysize)
  28.     void bmfree(b)
  29.     Bitmap *bmclone(b)
  30.     void bmop(b,op)
  31.     void bmclear(b)
  32.     void bmset(b)
  33.     void bmxor(b)
  34.     void bmrand(b)
  35.     void bmpixop(b,x,y,op)
  36.     void bmclrpix(b,x,y)
  37.     void bmsetpix(b,x,y)
  38.     void bmxorpix(b,x,y)
  39.     void bmbmop(dst,x,y,src,op)
  40.     void bmzap(b)
  41.     Bitmap *bmmagnify(b,xmag,ymag)
  42.     Bitmap *bmminimize(b)
  43.     int bmgetpix(b,x,y)
  44.     int bmdomain(b,xmin,ymin,xmax,ymax)
  45.     int bmrasbytes(b)
  46.     Bitmap *bmread(fname)
  47.     Bitmap *bmfromfile(inf)
  48.     void bmwrite(fname,b)
  49.     void bmtofile(outf,b)
  50.     void putbm(port,b)
  51.     Bitmap *getbm(val)
  52.     void bmdrawbig(b,mag)
  53.     void bmbigpix(b,x,y,mag)
  54.     void bmprint(bm)
  55.  *
  56.  */
  57. #include "gl.h"
  58. #include "device.h"
  59. #include "stdio.h"
  60. #include "port.h"
  61. #include "bitmap.h"
  62. #include "obj.h"
  63. #include "rct.h"
  64.  
  65. FILE *gfxopen();
  66.  
  67. #define BMMAGIC        0x5421
  68.  
  69. static leftmost();
  70. static rightmost();
  71.  
  72. static int bittab[16] = {
  73.     0x8000, 0x4000, 0x2000, 0x1000,
  74.     0x0800, 0x0400, 0x0200, 0x0100,
  75.     0x0080, 0x0040, 0x0020, 0x0010,
  76.     0x0008, 0x0004, 0x0002, 0x0001,
  77. };
  78.  
  79. Bitmap *bmnew(xsize,ysize)
  80. int xsize, ysize;
  81. {
  82.     Bitmap *b;
  83.  
  84.     b = (Bitmap *)mymalloc(sizeof(Bitmap));
  85.     b->xsize = xsize;
  86.     b->ysize = ysize;
  87.     b->xorig = 0;
  88.     b->yorig = 0;
  89.     b->xmove = 0;
  90.     b->ymove = 0;
  91.     if(b->ysize>0 && b->ysize>0) {
  92.     b->sper = 1+((b->xsize-1)>>4);
  93.     b->base = (short *)mymalloc(bmrasbytes(b)); 
  94.     bzero(b->base,bmrasbytes(b));
  95.     } else {
  96.     b->sper = 0;
  97.     b->xsize = 0;
  98.     }
  99.     return b;
  100. }
  101.  
  102. void bmfree(b)
  103. Bitmap *b;
  104. {
  105.     if(b->base)
  106.     free(b->base);
  107.     free(b);
  108. }
  109.  
  110. Bitmap *bmclone(b)
  111. Bitmap *b;
  112. {
  113.     Bitmap *c;
  114.  
  115.     c = bmnew(b->xsize,b->ysize); 
  116.     c->xmove = b->xmove;
  117.     c->ymove = b->ymove;
  118.     c->xorig = b->xorig;
  119.     c->yorig = b->yorig;
  120.     if(b->base)
  121.     bcopy(b->base,c->base,bmrasbytes(b));
  122.     return c;
  123. }
  124.  
  125. void bmop(b,op)
  126. Bitmap *b;
  127. int op;
  128. {
  129.     short *sptr;
  130.     int n;
  131.  
  132.     n = b->sper * b->ysize;
  133.     sptr = b->base;
  134.     switch(op) {
  135.     case BM_CLR:
  136.         while(n--) 
  137.         *sptr++ = 0;
  138.         break;
  139.     case BM_SET:
  140.         while(n--) 
  141.         *sptr++ = 0xffff;
  142.         break;
  143.     case BM_XOR:
  144.         while(n--) 
  145.         *sptr++ ^= 0xffff;
  146.         break;
  147.     }
  148. }
  149.  
  150. void bmclear(b)
  151. Bitmap *b;
  152. {
  153.     bmop(b,BM_CLR);
  154. }
  155.  
  156. void bmset(b)
  157. Bitmap *b;
  158. {
  159.     bmop(b,BM_SET);
  160. }
  161.  
  162. void bmxor(b)
  163. Bitmap *b;
  164. {
  165.     bmop(b,BM_XOR);
  166. }
  167.  
  168. void bmrand(b)
  169. Bitmap *b;
  170. {
  171.     char *cptr;
  172.     short *sptr;
  173.     int n, i;
  174.  
  175.     n = bmrasbytes(b);
  176.     cptr = (char *)b->base;
  177.     i = 0;
  178.     while(n--) 
  179.     *cptr++ = rand();
  180. }
  181.  
  182. void bmpixop(b,x,y,op)
  183. Bitmap *b;
  184. unsigned int x, y;
  185. int op;
  186. {
  187.     int offset;
  188.  
  189.     if( (x>=b->xsize) || (y>=b->ysize) ) {
  190.     fprintf(stderr,"bmpixop: range error\n");
  191.     return;
  192.     }
  193.     offset = y*b->sper + (x >> 4); 
  194.     switch(op) {
  195.     case BM_CLR:
  196.         b->base[offset] &= ~bittab[x&0xf];
  197.         break;
  198.     case BM_SET:
  199.         b->base[offset] |= bittab[x&0xf];
  200.         break;
  201.     case BM_XOR:
  202.         b->base[offset] ^= bittab[x&0xf];
  203.         break;
  204.     }
  205. }
  206.  
  207. void bmclrpix(b,x,y)
  208. Bitmap *b;
  209. unsigned int x, y;
  210. {
  211.     bmpixop(b,x,y,BM_CLR);
  212. }
  213.  
  214. void bmsetpix(b,x,y)
  215. Bitmap *b;
  216. unsigned int x, y;
  217. {
  218.     bmpixop(b,x,y,BM_SET);
  219. }
  220.  
  221. void bmxorpix(b,x,y)
  222. Bitmap *b;
  223. unsigned int x, y;
  224. {
  225.     bmpixop(b,x,y,BM_XOR);
  226. }
  227.  
  228. void bmbmop(dst,x,y,src,op)
  229. Bitmap *dst, *src;
  230. unsigned int x, y;
  231. int op;
  232. {
  233.     int xmax, doff;
  234.     int srcymin, srcymax;
  235.     int xsrc, ysrc, ydst;
  236.     unsigned short *sptr;
  237.     unsigned short *dptr;
  238.     rct srct, drct, irct;
  239.  
  240.     srct.xmin = 0;
  241.     srct.ymin = 0;
  242.     srct.xmax = 0+src->xsize;
  243.     srct.ymax = 0+src->ysize;
  244.     drct.xmin = -x;
  245.     drct.ymin = -y;
  246.     drct.xmax = dst->xsize-x;
  247.     drct.ymax = dst->ysize-y;
  248.     if(!rctinter(&srct,&drct,&irct))
  249.     return;
  250.  
  251.     srcymin = irct.ymin;
  252.     srcymax = irct.ymax;
  253.     xmax = src->xsize;
  254.     for(ysrc=srcymin; ysrc<srcymax; ysrc++) {
  255.     ydst = ysrc+y;
  256.     sptr = (unsigned short *)(src->base+(ysrc*src->sper));
  257.     dptr = (unsigned short *)(dst->base+((ydst*dst->sper)+(x>>4)));
  258.     doff = x&0xf;
  259.     if(doff == 0) { 
  260.         switch(op) {
  261.         case BM_CLR:
  262.             for(xsrc=0; xsrc<xmax; xsrc+=16) 
  263.             *dptr++ &= ~(*sptr++);
  264.             break;
  265.         case BM_SET:
  266.             for(xsrc=0; xsrc<xmax; xsrc+=16) 
  267.             *dptr++ |= *sptr++;
  268.             break;
  269.         case BM_XOR:
  270.             for(xsrc=0; xsrc<xmax; xsrc+=16) 
  271.             *dptr++ ^= *sptr++;
  272.             break;
  273.         }
  274.     } else {
  275.         for(xsrc=0; xsrc<xmax; xsrc+=16) {
  276.         switch(op) {
  277.             case BM_CLR:
  278.             *dptr &= ~(*sptr>>doff);
  279.             dptr++;
  280.             *dptr &= ~(*sptr<<(16-doff));
  281.             sptr++;
  282.             break;
  283.             case BM_SET:
  284.             *dptr |= *sptr>>doff;
  285.             dptr++;
  286.             *dptr |= *sptr<<(16-doff);
  287.             sptr++;
  288.             break;
  289.             case BM_XOR:
  290.             *dptr ^= *sptr>>doff;
  291.             dptr++;
  292.             *dptr ^= *sptr<<(16-doff);
  293.             sptr++;
  294.             break;
  295.         }
  296.         }
  297.     }
  298.     }
  299. }
  300.  
  301. void bmzap(b)
  302. Bitmap *b;
  303. {
  304.     b->xmove = 0;
  305.     b->ymove = 0;
  306.     b->xorig = 0;
  307.     b->yorig = 0;
  308. }
  309.  
  310. Bitmap *bmmagnify(b,xmag,ymag)
  311. Bitmap *b;
  312. int xmag, ymag;
  313. {
  314.     Bitmap *c;
  315.     short *sptr;
  316.     int word;
  317.     int x, y;
  318.     int m;
  319.     int xpos, rowstart;
  320.     int offset;
  321.  
  322.     c = bmnew(xmag*b->xsize,ymag*b->ysize); 
  323.     c->xmove = xmag*b->xmove;
  324.     c->ymove = ymag*b->ymove;
  325.     c->xorig = xmag*b->xorig;
  326.     c->yorig = ymag*b->yorig;
  327.     sptr = c->base; 
  328.     rowstart = ymag*y*c->sper;
  329.     for(y=0; y<b->ysize; y++) {
  330.     xpos = 0;
  331.     for(x=0; x<b->xsize; x++) {
  332.         if(bmgetpix(b,x,y)) {
  333.         for(m=0; m<xmag; m++) {
  334.             offset = rowstart + ((xpos) >> 4); 
  335.             word = sptr[offset];
  336.             word |= bittab[xpos&0xf];
  337.             sptr[offset] = word;
  338.             xpos++;
  339.         }
  340.         } else 
  341.         xpos += xmag;
  342.     }
  343.     for(m=0; m<(ymag-1); m++) {
  344.         bcopy(sptr+rowstart,sptr+rowstart+c->sper,c->sper<<1);
  345.         rowstart += c->sper; 
  346.     }
  347.     rowstart += c->sper;
  348.     }
  349.     return c;
  350. }
  351.  
  352. Bitmap *bmminimize(b)
  353. Bitmap *b;
  354. {
  355.     Bitmap *c;
  356.     int x, y;
  357.     int xsize, ysize;
  358.     int xmin, ymin, xmax, ymax;
  359.  
  360.     if(bmdomain(b,&xmin,&ymin,&xmax,&ymax)) {
  361.     xsize = xmax-xmin+1;
  362.     ysize = ymax-ymin+1;
  363.     c = bmnew(xsize,ysize);
  364.     for(y=0; y<ysize; y++)
  365.         for(x=0; x<xsize; x++) {
  366.         if(bmgetpix(b,x+xmin,y+ymin))
  367.             bmsetpix(c,x,y);
  368.         }
  369.     c->xorig = b->xorig-xmin;
  370.     c->yorig = b->yorig-ymin;
  371.     } else {
  372.     c = bmnew(1,1);
  373.     }
  374.     c->xmove = b->xmove;
  375.     c->ymove = b->ymove;
  376.     return c;
  377. }
  378.  
  379. int bmgetpix(b,x,y)
  380. Bitmap *b;
  381. unsigned int x, y;
  382. {
  383.     int offset;
  384.  
  385.     if( (x>=b->xsize) || (y>=b->ysize) ) {
  386.     fprintf(stderr,"bmgetpix: range error\n");
  387.     return 0;
  388.     }
  389.     offset = y*b->sper + (x >> 4); 
  390.     if(b->base[offset] & bittab[x&0xf])
  391.         return 1;
  392.     else
  393.         return 0;
  394. }
  395.  
  396. int bmdomain(b,xmin,ymin,xmax,ymax)
  397. Bitmap *b;
  398. int *xmin, *ymin, *xmax, *ymax;
  399. {
  400.     int x, y;
  401.     int ixmin, ixmax;
  402.     int iymin, iymax;
  403.     short *sptr;
  404.     int xoffset;
  405.     int temp;
  406.     short excessmask;
  407.  
  408.     sptr = b->base;
  409.     iymin = 100000;
  410.     iymax = -100000;
  411.     ixmin = 100000;
  412.     ixmax = -100000;
  413.     excessmask = 0xffff<<(15-((b->xsize-1)&0xf));
  414.     for(y=0; y<b->ysize; y++) {
  415.     xoffset = 0;
  416.     for(x=0; x<b->sper; x++) {
  417.         if(x == (b->sper-1))
  418.         *sptr &= excessmask; 
  419.         if(*sptr) {
  420.         temp = xoffset + leftmost(*sptr);
  421.         if(temp<ixmin)
  422.             ixmin = temp;
  423.         temp = xoffset + rightmost(*sptr);
  424.         if(temp>ixmax)
  425.             ixmax = temp;
  426.                if(y<iymin) 
  427.             iymin = y;
  428.                if(y>iymax) 
  429.             iymax = y;
  430.         }
  431.         sptr++;
  432.         xoffset += 16;
  433.     }
  434.     }
  435.     if(iymin>iymax) {
  436.     *xmin = 0;
  437.     *xmax = 0;
  438.     *ymin = 0;
  439.     *ymax = 0;
  440.     return 0;
  441.     } else {
  442.     *xmin = ixmin;
  443.     *xmax = ixmax;
  444.     *ymin = iymin;
  445.     *ymax = iymax;
  446.     return 1;
  447.     }
  448. }
  449.  
  450. static leftmost(val)
  451. short val;
  452. {
  453.     int i;
  454.     int bit;
  455.  
  456.     bit = 0x8000;
  457.     for(i=0; i<16; i++) {
  458.     if(bit&val)
  459.         return i;
  460.     bit >>= 1;
  461.     }
  462.     return 0;
  463. }
  464.  
  465. static rightmost(val)
  466. short val;
  467. {
  468.     int i;
  469.     int bit;
  470.  
  471.     bit = 0x1;
  472.     for(i=16; i--;) {
  473.     if(bit&val)
  474.         return i;
  475.     bit <<= 1;
  476.     }
  477.     return 0;
  478. }
  479.  
  480. int bmrasbytes(b)
  481. Bitmap *b;
  482. {
  483.     return b->ysize*2*b->sper;
  484. }
  485.  
  486. Bitmap *bmread(fname)
  487. char *fname;
  488. {
  489.     FILE *inf;
  490.     Bitmap *b;
  491.  
  492.     inf = gfxopen(fname,"r");
  493.     if(!inf) {
  494.     fprintf(stderr,"bmread: can't open input file [%s]\n",fname);
  495.     exit(1);
  496.     }
  497.     b = bmfromfile(inf);
  498.     fclose(inf);
  499.     return b;
  500. }
  501.  
  502. Bitmap *bmfromfile(inf)
  503. FILE *inf;
  504. {
  505.     Bitmap *b;
  506.     long magic[2];
  507.  
  508.     fread(magic,2*sizeof(long),1,inf);
  509.     if(magic[0] != BMMAGIC || magic[1] != BMMAGIC) {
  510.     fprintf(stderr,"bad magic number in bit map header\n");
  511.     return 0;
  512.     }
  513.     b = (Bitmap *)mymalloc(sizeof(Bitmap));
  514.     fread(&b->base,sizeof(short *),1,inf);
  515.     fread(&b->xsize,sizeof(short),1,inf);
  516.     fread(&b->ysize,sizeof(short),1,inf);
  517.     fread(&b->xorig,sizeof(short),1,inf);
  518.     fread(&b->yorig,sizeof(short),1,inf);
  519.     fread(&b->xmove,sizeof(short),1,inf);
  520.     fread(&b->ymove,sizeof(short),1,inf);
  521.     fread(&b->sper,sizeof(short),1,inf);
  522.     b->base = (short *)mymalloc(bmrasbytes(b)); 
  523.     fread(b->base,bmrasbytes(b),1,inf);
  524.     return b;
  525. }
  526.  
  527. void bmtofile(outf,b)
  528. FILE *outf;
  529. Bitmap *b;
  530. {
  531.     long magic[2];
  532.  
  533.     magic[0] = BMMAGIC;
  534.     magic[1] = BMMAGIC;
  535.     fwrite(magic,2*sizeof(long),1,outf);
  536.     fwrite(&b->base,sizeof(short *),1,outf);
  537.     fwrite(&b->xsize,sizeof(short),1,outf);
  538.     fwrite(&b->ysize,sizeof(short),1,outf);
  539.     fwrite(&b->xorig,sizeof(short),1,outf);
  540.     fwrite(&b->yorig,sizeof(short),1,outf);
  541.     fwrite(&b->xmove,sizeof(short),1,outf);
  542.     fwrite(&b->ymove,sizeof(short),1,outf);
  543.     fwrite(&b->sper,sizeof(short),1,outf);
  544.     fwrite(b->base,bmrasbytes(b),1,outf);
  545. }
  546.  
  547. void bmwrite(fname,b)
  548. char *fname;
  549. Bitmap *b;
  550. {
  551.     FILE *outf;
  552.  
  553.     outf = gfxopen(fname,"w");
  554.     if(!outf) {
  555.     fprintf(stderr,"bmwrite: can't open output file [%s]\n",fname);
  556.     exit(1);
  557.     }
  558.     bmtofile(outf,b);
  559.     fclose(outf);
  560. }
  561.  
  562. void bmdrawbig(b,mag)
  563. Bitmap *b;
  564. int mag;
  565. {
  566.     int x, y;
  567.     int bx, by;
  568.     int cdark, cbright;
  569.  
  570.     by = 0;
  571.     cdark = grey(0.1);
  572.     cbright = grey(0.9);
  573.     for(y=0; y<b->ysize; y++) {
  574.     bx = 0;
  575.     for(x=0; x<b->xsize; x++) {
  576.         if(bmgetpix(b,x,y)) 
  577.         usecolor(cdark);
  578.         else
  579.         usecolor(cbright);
  580.         fillrecti(bx,by,bx+(mag-2),by+(mag-2));
  581.         if(x == b->xorig && y == b->yorig) {
  582.         rgb(1.0,0.0,0.0);
  583.         recti(bx,by,bx+(mag-2),by+(mag-2));
  584.         }
  585.         bx += mag;
  586.         
  587.     }
  588.     by += mag;
  589.     }
  590. }
  591.  
  592. void bmbigpix(b,x,y,mag)
  593. Bitmap *b;
  594. int x, y;
  595. int mag;
  596. {
  597.     int bx, by;
  598.  
  599.     if(bmgetpix(b,x,y)) 
  600.     grey(0.1);
  601.     else
  602.     grey(0.9);
  603.     bx = x*mag;
  604.     by = y*mag;
  605.     fillrecti(bx,by,bx+(mag-2),by+(mag-2));
  606.     if(x == b->xorig && y == b->yorig) {
  607.     rgb(1.0,0.0,0.0);
  608.     recti(bx,by,bx+(mag-2),by+(mag-2));
  609.     }
  610. }
  611.  
  612. void bmprint(bm)
  613. Bitmap *bm;
  614. {
  615.     printf("Bitmap size %d by %d\n",bm->xsize,bm->ysize);
  616.     printf("Bitmap orig %d by %d\n",bm->xorig,bm->yorig);
  617.     printf("Bitmap move %d by %d\n",bm->xmove,bm->ymove);
  618.     printf("Bitmap sper %d\n",bm->sper);
  619.     printf("Bitmap data %x\n",bm->base);
  620. }
  621.